//
// Created by user on 20-5-4.
//

#include "Spinlock.h"
#include "Preempt.h"

inline void spinInit(spinlock_T *lock) {

    // 关闭自旋锁
    lock->lock = 1;

}

inline void spinLock(spinlock_T *lock) {

    preemptDisable();

    // 通过 decq 指令将 lock->lock 自减1,如果指向结构是非负数就跳到3
    // 否则就执行2的代码，2的代码就是判断 0 是否小于等于 lock->lock
    // 如果小于等于的话，就继续循环，否则就跳出循环去 代码1 加锁
    __asm__ __volatile__    (
    "1:	\n\t"
            "lock	decq	%0	\n\t"
            "jns	3f	\n\t"
            "2:	\n\t"
            "pause	\n\t"
            "cmpq	$0,	%0	\n\t"
            "jle	2b	\n\t"
            "jmp	1b	\n\t"
            "3:	\n\t"
    :"=m"(lock->lock)
    :
    :"memory"
    );
}

inline void spinUnlock(spinlock_T *lock) {

    __asm__ __volatile__    (
    "movq	$1,	%0	\n\t"
    :"=m"(lock->lock)
    :
    :"memory"
    );

    preemptEnable();
}

inline long spinTryLock(spinlock_T *lock) {

    unsigned long tmpValue = 0;

    preemptDisable();

    __asm__ __volatile__    (
        "xchgq	%0,	%1	\n\t"
    :"=q"(tmpValue), "=m"(lock->lock)
    :"0"(0)
    :"memory"
    );

    if (!tmpValue)
        preemptEnable();

    return tmpValue;
}